package com.yeskery.nut.websocket;

import com.yeskery.nut.core.KeyAndValue;
import com.yeskery.nut.core.NutException;
import com.yeskery.nut.core.PathMatcher;
import com.yeskery.nut.core.PathMetadata;

import java.util.*;

/**
 * WebSocket 配置注册中心
 * @author sprout
 * @version 1.0
 * 2023-04-22 15:42
 */
public class WebSocketConfigurationRegistry implements WebSocketLoader, WebSocketConfigurationManager {

    /** 动态路径前缀 */
    private static final String DYNAMIC_PATH_PREFIX = "$";

    /** 用于缓存静态websocket的载体 */
    private final Map<String, WebSocketConfiguration> websocketRegisterCacheMap = new HashMap<>();

    /** 用于缓存动态websocket配置的载体 */
    private final Set<DynamicWebSocketConfigurationRegisterMetadata> dynamicWebSocketConfigurationRegisterMetadataSet = new HashSet<>();

    /** websocket Path缓存 */
    private final Set<String> websocketPathCacheSet = new HashSet<>();

    @Override
    public void registerEndpoints(Collection<WebSocketConfiguration> webSocketConfigurations) {
        for (WebSocketConfiguration webSocketConfiguration : webSocketConfigurations) {
            WebSocketServerConfigure webSocketServerConfigure = webSocketConfiguration.getWebSocketServerConfigure();
            PathMetadata pathMetadata = webSocketServerConfigure.getPathMetadata();
            if (pathMetadata.isDynamic()) {
                if (!websocketPathCacheSet.add(DYNAMIC_PATH_PREFIX + webSocketServerConfigure.getPath())) {
                    throw new NutException("Websocket Path [" + webSocketServerConfigure.getPath() + "] Already Registered.");
                }
                DynamicWebSocketConfigurationRegisterMetadata metadata = new DynamicWebSocketConfigurationRegisterMetadata(
                        Arrays.stream(pathMetadata.getParamNameAndPatterns()).map(KeyAndValue::getKey).toArray(String[]::new),
                        new PathMatcher(pathMetadata.getPathPattern()), webSocketConfiguration);
                dynamicWebSocketConfigurationRegisterMetadataSet.add(metadata);
            } else {
                if (!websocketPathCacheSet.add(webSocketServerConfigure.getPath())) {
                    throw new NutException("Websocket Path [" + webSocketServerConfigure.getPath() + "] Already Registered.");
                }
                websocketRegisterCacheMap.put(webSocketServerConfigure.getPath(), webSocketConfiguration);
            }
        }
    }

    @Override
    public WebSocketConfiguration findWebSocketConfiguration(String path) {
        WebSocketConfiguration webSocketConfiguration = websocketRegisterCacheMap.get(path);
        if (webSocketConfiguration == null) {
            // 尝试从动态路径中获取webSocket配置对象
            for (DynamicWebSocketConfigurationRegisterMetadata metadata : dynamicWebSocketConfigurationRegisterMetadataSet) {
                if (metadata.getPathMatcher().match(path)) {
                    webSocketConfiguration = metadata.getWebSocketConfiguration();
                    break;
                }
            }
        }
        return webSocketConfiguration;
    }
}
